package com.jwgf.smarowindingmachine_unity.logic;

import com.jwgf.common.AppContext;
import com.jwgf.common.Utility;
import com.jwgf.group.Group;
import com.jwgf.group.GroupMap;
import com.jwgf.objectbox.ObjectBox;
import com.jwgf.objectbox.SpindleParameter;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class CanCommand {

    private static MachineParameterSharedPreference sp = MachineParameterSharedPreference.getInstance();

    public static List<byte[]> initAll() {
        List<byte[]> cmdList = new ArrayList<>();
        cmdList.add(getBus());
        cmdList.add(getADCmd());
        cmdList.addAll(getAllGroupCmd());
        cmdList.add(releaseBus());
        return cmdList;
    }

    public static List<byte[]> initSpindle(int spindle) {
        long id = GroupMap.getInstance().getSpindleParameterIdFromSpindle(spindle);
        SpindleParameter parameter;
        if (id != 0) {
            parameter = ObjectBox.get().boxFor(SpindleParameter.class).get(id);
        } else {
            parameter = new SpindleParameter();
        }
        List<byte[]> cmdList = new ArrayList<>();
        cmdList.add(getBus());
        cmdList.addAll(getSpindleCmd(spindle, parameter));
        cmdList.add(releaseBus());
        return cmdList;
    }

    public static List<byte[]> initGroup(int group) {
        List<byte[]> cmdList = new ArrayList<>();
        cmdList.add(getBus());
        cmdList.addAll(getGroupCmd(group));
        cmdList.add(releaseBus());
        return cmdList;
    }

    public static List<byte[]> intAllGroup() {
        List<byte[]> cmdList = new ArrayList<>();
        cmdList.add(getBus());
        cmdList.addAll(getAllGroupCmd());
        cmdList.add(releaseBus());
        return cmdList;
    }

    public static List<byte[]> getSpindleCmd(int spindle, SpindleParameter parameter) {
        int spindleCnt = Integer.valueOf(sp.getValue(0x29, 1));
        int currentPulse = Report.getInstance().getCurrentPulse(spindle);

        List<byte[]> cmdList = new ArrayList<>();
        cmdList.add(createSpindleCmd20(spindle, parameter));
        cmdList.add(createSpindleCmd21(spindle, parameter));
        cmdList.add(createSpindleCmd22(spindle, parameter));
        cmdList.add(createSpindleCmd23(spindle, parameter));
        cmdList.add(createSpindleCmd24(spindle, parameter));
        cmdList.add(createSpindleCmd25(spindle, parameter));
        cmdList.add(createSpindleCmd26(spindle, parameter));
        cmdList.add(createSpindleCmd27(spindle, parameter));
        cmdList.add(createSpindleCmd28(spindle, parameter));
        cmdList.add(createSpindleCmd29(spindle, currentPulse, spindleCnt));
        cmdList.add(createSpindleCmd2A(spindle, parameter));
        cmdList.add(createSpindleCmd2E(spindle, parameter));
        if (!AppContext.isReform) {
            cmdList.add(createSpindleCmd2C(spindle, parameter));
            cmdList.add(createSpindleCmd39(spindle));
            cmdList.add(createSpindleCmd15(spindle, parameter));
            cmdList.add(createSpindleCmd10(spindle, parameter));
            cmdList.add(createSpindleCmd16(spindle, parameter));
            cmdList.add(createSpindleCmd1F(spindle));
            cmdList.add(createSpindleCmd13(spindle, parameter));
            cmdList.add(createSpindleCmd11(spindle, parameter));
        }

        return cmdList;
    }

    public static List<byte[]> getGroupCmd(int group) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        long id = GroupMap.getInstance().getSpindleParameterIdFromGroup(group);
        SpindleParameter parameter;
        if (id != 0) {
            parameter = ObjectBox.get().boxFor(SpindleParameter.class).get(id);
        } else {
            parameter = new SpindleParameter();
        }

        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.addAll(getSpindleCmd(spindle, parameter));
        }
        return cmdList;
    }

    public static List<byte[]> getAllGroupCmd() {
        List<Group> groups = GroupMap.getInstance().getGroupList();
        List<byte[]> cmdList = new ArrayList<>();
        for (int i = 0; i < groups.size(); ++i) {
            cmdList.addAll(getGroupCmd(i + 1));
        }
        return cmdList;
    }

    public static byte[] getADCmd() {
        int spindleCnt = Integer.valueOf(sp.getValue(0x29, 1));
        return createSingle(0x9F, 0x75, 508, spindleCnt, 0);
    }

    public static byte[] getBus() {
        return new byte[]{0x00, 0x55, (byte) 0xAA, 0x01, 0, 0, 0, 0, 0, 0};
    }

    public static byte[] releaseBus() {
        return new byte[]{0x00, 0x55, 0x55, 0x01, 0, 0, 0, 0, 0, 0};
    }

    public static byte[] createSingle(int spindle, int da, int db, int dc, int dd) {
        byte[] id = Utility.ByteArrayUtils.short2ByteArray((short) (spindle + 1));
        byte[] daArray = Utility.ByteArrayUtils.short2ByteArray((short) ((da << 8) | 0x01));
        byte[] dbArray = Utility.ByteArrayUtils.short2SwapByteArray((short) db);
        byte[] dcArray = Utility.ByteArrayUtils.short2SwapByteArray((short) dc);
        byte[] ddArray = Utility.ByteArrayUtils.short2SwapByteArray((short) dd);
        byte[] cmd = Utility.ByteArrayUtils.concatAll(id, daArray, dbArray, dcArray, ddArray);
        return cmd;
    }

    public static byte[] createSpindleCmd10(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame10DB);
        int dc = Integer.parseInt(para.frame10DC);
        int dd = 0;
        return createSingle(spindle, 0x10, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd10(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd10(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd11(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame11DB);
        int dc = Integer.parseInt(para.frame11DCH) << 8 | Integer.parseInt(para.frame11DCL);
        int dd = Integer.parseInt(para.frame11DDH) << 8 | Integer.parseInt(para.frame11DDL);
        return createSingle(spindle, 0x11, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd11(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd11(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd13(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame13DB);
        int dc = 0;
        int dd = 0;
        return createSingle(spindle, 0x13, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd13(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd13(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd15(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame15DB);
        int dc = Integer.parseInt(para.frame15DC);
        int dd = Integer.parseInt(para.frame15DDH) << 8 | Integer.parseInt(para.frame15DDL);
        return createSingle(spindle, 0x15, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd15(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd15(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd16(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame16DB);
        int dc = Integer.parseInt(para.frame16DCH) << 8 | Integer.parseInt(para.frame16DCL);
        int dd = Integer.parseInt(para.frame16DDH) << 8 | Integer.parseInt(para.frame16DDL);
        return createSingle(spindle, 0x16, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd16(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd16(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd1D(int spindle, SpindleParameter para) {
        //在无槽筒版本，为测试数据，正式版还没用
//        return createSingle(spindle, 0x1D, para.frame1DDB, para.frame1DDC, 0);
        return null;
    }

    public static byte[] createSpindleCmd1F(int spindle) {
        Calendar calendar = Calendar.getInstance();
        int db = calendar.get(Calendar.YEAR);
        int dcH = calendar.get(Calendar.MONTH) + 1;
        int dcL = calendar.get(Calendar.DAY_OF_MONTH);
        int dc = dcH << 8 | dcL;
        return createSingle(spindle, 0x1F, db, dc, 0);
    }

    public static byte[] createSpindleCmd20(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame20DB);
        int dc = Integer.parseInt(para.frame20DC);
        int dd = Integer.parseInt(para.frame20DDH) << 8 | Integer.parseInt(para.frame20DDL);
        return createSingle(spindle, 0x20, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd20(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd20(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd21(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame21DB);
        int dc = Integer.parseInt(para.frame21DC);
        int dd = Integer.parseInt(para.frame21DDH) << 8 | Integer.parseInt(para.frame21DDL);
        return createSingle(spindle, 0x21, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd21(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd21(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd22(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame22DB);
        int dc = Integer.parseInt(para.frame22DC);
        int dd = Integer.parseInt(para.frame22DD);
        return createSingle(spindle, 0x22, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd22(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd22(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd23(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame23DB);
        int dc = Integer.parseInt(para.frame23DCH) << 8 | Integer.parseInt(para.frame23DCL);
        int dd = Integer.parseInt(para.frame23DD);
        return createSingle(spindle, 0x23, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd23(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd23(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd24(int spindle, SpindleParameter para) {
        int db = Math.round(Integer.parseInt(para.frame24DB) * UnitUtils.LENGTH_TO_PULSE_FACTOR
                * Float.parseFloat(para.slipCoefficient));
        int dc = Integer.parseInt(para.frame24DC);
        int dd = Math.round(Float.parseFloat(para.frame24DD) * 1024);
        return createSingle(spindle, 0x24, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd24(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd24(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd25(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame25DB);
        int dc = Integer.parseInt(para.frame25DC);
        int dd = Integer.parseInt(para.frame25DD);
        return createSingle(spindle, 0x25, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd25(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd25(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd26(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame26DB);
        int dc = Integer.parseInt(para.frame26DC);
        int dd = Integer.parseInt(para.frame26DD);
        return createSingle(spindle, 0x26, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd26(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd26(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd27(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame27DBH) << 8 | Integer.parseInt(para.frame27DBL);
        int dc = Integer.parseInt(para.frame27DCH) << 8 | Integer.parseInt(para.frame27DCL);
        int dd = Integer.parseInt(para.frame27DDH) << 8 | Integer.parseInt(para.frame27DDL);
        return createSingle(spindle, 0x27, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd27(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd27(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd28(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame28DB);
        int dc = Float.valueOf(para.frame28DC).intValue();
        int dd = Integer.parseInt(para.frame28DD);
        return createSingle(spindle, 0x28, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd28(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd28(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd29(int spindle, int currentPulse, int count) {
        return createSingle(spindle, 0x29, currentPulse, count, 0);
    }

    public static byte[] createSpindleCmd2A(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame2ADB);
        int dc = Integer.parseInt(para.frame2ADC);
        return createSingle(spindle, 0x2A, db, dc, 0);
    }

    public static List<byte[]> createGroupCmd2A(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd2A(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd2C(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame2CDB);
        int dc = Integer.parseInt(para.frame2CDC);
        int dd = Integer.parseInt(para.frame2CDD);
        return createSingle(spindle, 0x2C, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd2C(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd2C(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd2E(int spindle, SpindleParameter para) {
        int db = Integer.parseInt(para.frame2EDB);
        int dc = Integer.parseInt(para.frame2EDC);
        int dd = 0;
        return createSingle(spindle, 0x2E, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd2E(int group, SpindleParameter para) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd2E(spindle, para));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd37(int spindle, int db) {
        return createSingle(spindle, 0x37, db, 0, 0);
    }

    public static List<byte[]> createGroupCmd37(int group, int db) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd37(spindle, db));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmd39(int spindle) {
        int db = Integer.parseInt(sp.getValue(0x39, 0));
        int dc = Integer.parseInt(sp.getValue(0x39, 1));
        int dd = Integer.parseInt(sp.getValue(0x39, 2));
        return createSingle(spindle, 0x39, db, dc, dd);
    }

    public static List<byte[]> createGroupCmd39(int group) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmd39(spindle));
        }
        return cmdList;
    }

    public static byte[] createSpindleCmdFunction(int spindle, int da, int db, int dc) {
        return createSingle(spindle, da, db, dc, 0);
    }

    public static List<byte[]> createGroupCmdFunction(int group, int da, int db) {
        List<Integer> spindles = GroupMap.getInstance().getSpindleList(group);
        List<byte[]> cmdList = new ArrayList<>();
        for (Integer spindle : spindles) {
            cmdList.add(createSpindleCmdFunction(spindle, da, db, 0));
        }
        return cmdList;
    }

    public static List<byte[]> createAllCmd29(int dc) {
        int spindleCount = dc;
        List<byte[]> cmdList = new ArrayList<>();
        for (int i = 0; i < spindleCount; ++i) {
            int currentPulse = Report.getInstance().getCurrentPulse(i + 1);
            cmdList.add(createSpindleCmd29(i + 1, currentPulse, dc));
        }
        return cmdList;
    }

    public static List<byte[]> createAllCmdFunction(int da, int db) {
        List<Group> groups = GroupMap.getInstance().getGroupList();
        List<byte[]> cmdList = new ArrayList<>();
        for (int i = 0; i < groups.size(); ++i) {
            cmdList.addAll(createGroupCmdFunction(i + 1, da, db));
        }
        return cmdList;
    }


}
